"""
SQLAlchemy ORM models for SkyWalking data storage.
Supports both SQLite and PostgreSQL through configuration.
"""

from datetime import datetime
from sqlalchemy import (
    Column, Integer, String, Float, Boolean, DateTime, 
    Text, ForeignKey, Index, create_engine
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

Base = declarative_base()


class Service(Base):
    """服务信息表"""
    __tablename__ = 'services'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    service_id = Column(String(255), unique=True, nullable=False, index=True)  # SkyWalking service ID
    name = Column(String(255), nullable=False, index=True)
    layer = Column(String(100))
    group = Column(String(255))
    collected_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    
    # Relationships
    metrics = relationship("ServiceMetric", back_populates="service", cascade="all, delete-orphan")
    endpoints = relationship("Endpoint", back_populates="service", cascade="all, delete-orphan")
    traces = relationship("Trace", back_populates="service", cascade="all, delete-orphan")
    
    def __repr__(self):
        return f"<Service(id={self.id}, name='{self.name}', service_id='{self.service_id}')>"


class ServiceMetric(Base):
    """服务指标表"""
    __tablename__ = 'service_metrics'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    service_id = Column(Integer, ForeignKey('services.id', ondelete='CASCADE'), nullable=False, index=True)
    metric_name = Column(String(100), nullable=False, index=True)  # e.g., 'response_time', 'throughput', 'success_rate'
    value = Column(Float, nullable=False)
    timestamp = Column(DateTime, nullable=False, index=True)
    collected_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    
    # Relationship
    service = relationship("Service", back_populates="metrics")
    
    # Composite index for efficient queries
    __table_args__ = (
        Index('ix_service_metric_time', 'service_id', 'metric_name', 'timestamp'),
    )
    
    def __repr__(self):
        return f"<ServiceMetric(service_id={self.service_id}, metric='{self.metric_name}', value={self.value})>"


class Endpoint(Base):
    """端点信息表"""
    __tablename__ = 'endpoints'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    service_id = Column(Integer, ForeignKey('services.id', ondelete='CASCADE'), nullable=False, index=True)
    endpoint_id = Column(String(255), unique=True, nullable=False, index=True)  # SkyWalking endpoint ID
    name = Column(String(500), nullable=False)
    collected_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    
    # Relationships
    service = relationship("Service", back_populates="endpoints")
    metrics = relationship("EndpointMetric", back_populates="endpoint", cascade="all, delete-orphan")
    
    def __repr__(self):
        return f"<Endpoint(id={self.id}, name='{self.name}')>"


class EndpointMetric(Base):
    """端点指标表"""
    __tablename__ = 'endpoint_metrics'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    endpoint_id = Column(Integer, ForeignKey('endpoints.id', ondelete='CASCADE'), nullable=False, index=True)
    metric_name = Column(String(100), nullable=False, index=True)  # e.g., 'response_time', 'throughput'
    value = Column(Float, nullable=False)
    timestamp = Column(DateTime, nullable=False, index=True)
    collected_at = Column(DateTime, default=datetime.utcnow, nullable=False)
    
    # Relationship
    endpoint = relationship("Endpoint", back_populates="metrics")
    
    # Composite index for efficient queries
    __table_args__ = (
        Index('ix_endpoint_metric_time', 'endpoint_id', 'metric_name', 'timestamp'),
    )
    
    def __repr__(self):
        return f"<EndpointMetric(endpoint_id={self.endpoint_id}, metric='{self.metric_name}', value={self.value})>"


class Trace(Base):
    """Trace 记录表"""
    __tablename__ = 'traces'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    trace_id = Column(String(255), nullable=False, index=True)  # SkyWalking trace ID (可能有多个 segment)
    service_id = Column(Integer, ForeignKey('services.id', ondelete='CASCADE'), nullable=False, index=True)
    segment_id = Column(String(255), unique=True, nullable=False)  # Segment ID 是真正唯一的
    endpoint_names = Column(Text)  # JSON string of endpoint names
    duration = Column(Integer, nullable=False)  # Duration in milliseconds
    start_time = Column(DateTime, nullable=False, index=True)
    is_error = Column(Boolean, default=False, nullable=False, index=True)
    collected_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    
    # Relationship
    service = relationship("Service", back_populates="traces")
    
    # Composite indexes for efficient queries
    __table_args__ = (
        Index('ix_trace_service_time', 'service_id', 'start_time'),
        Index('ix_trace_error', 'is_error', 'start_time'),
        Index('ix_trace_id', 'trace_id'),  # 允许按 trace_id 查询所有 segment
    )
    
    def __repr__(self):
        return f"<Trace(id={self.id}, trace_id='{self.trace_id}', duration={self.duration}ms, error={self.is_error})>"


class CollectionLog(Base):
    """采集日志表"""
    __tablename__ = 'collection_logs'
    
    id = Column(Integer, primary_key=True, autoincrement=True)
    status = Column(String(50), nullable=False, index=True)  # 'success', 'partial', 'failed'
    message = Column(Text)
    services_collected = Column(Integer, default=0)
    endpoints_collected = Column(Integer, default=0)
    traces_collected = Column(Integer, default=0)
    metrics_collected = Column(Integer, default=0)
    error_details = Column(Text)  # JSON string of error details
    collected_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    
    def __repr__(self):
        return f"<CollectionLog(id={self.id}, status='{self.status}', collected_at='{self.collected_at}')>"


def create_tables(engine):
    """Create all tables in the database."""
    Base.metadata.create_all(engine)


def drop_tables(engine):
    """Drop all tables in the database (use with caution!)."""
    Base.metadata.drop_all(engine)

